import { _decorator } from 'cc'
import { EnemyManager } from '../../Base/EnemyManager'
import { EntityManager } from '../../Base/EntityManager'
import { CONTROLLER_ENUM, DIRECTION_ENUM, ENTITY_STATE_ENUM, EVENT_ENUM, SHAKE_TYPE_ENUM } from '../../Enums'
import { IEntity } from '../../Levels'
import DataManager from '../../Runtime/DataManager'
import EventManager from '../../Runtime/EventManager'
import { BurstManager } from '../Burst/BurstManager'
import { TileManager } from '../Tile/TileManager'
import { PlayerStateMachine } from './PlayerStateMachine'
const { ccclass } = _decorator

@ccclass('PlayerManager')
export class PlayerManager extends EntityManager {
  targetX: number = 0
  targetY: number = 0
  isMoving: boolean = false
  private readonly speed: number = 0.1

  async init(params: IEntity) {
    // 初始化状态机
    this.fsm = this.addComponent(PlayerStateMachine)
    await this.fsm.init()
    super.init(params)

    this.targetX = this.x
    this.targetY = this.y
    // 监听玩家控制事件
    EventManager.Instance.on(EVENT_ENUM.PLAYER_CONTROL, this.inputHandle, this)
    // 监听玩家受到攻击事件
    EventManager.Instance.on(EVENT_ENUM.ATTACK_PLAYER, this.onDead, this)
  }

  onDestroy() {
    super.onDestroy()
    EventManager.Instance.off(EVENT_ENUM.PLAYER_CONTROL, this.inputHandle)
    EventManager.Instance.off(EVENT_ENUM.ATTACK_PLAYER, this.onDead)
  }

  update() {
    this.updateXY()
    super.update()
  }

  updateXY() {
    if (this.targetX < this.x) {
      this.x -= this.speed
    } else if (this.targetX > this.x) {
      this.x += this.speed
    }
    if (this.targetY < this.y) {
      this.y -= this.speed
    } else if (this.targetY > this.y) {
      this.y += this.speed
    }

    // 距离很近时，直接设置为目标位置，防止鬼畜
    if (
      Math.abs(this.targetX - this.x) <= this.speed &&
      Math.abs(this.targetY - this.y) <= this.speed &&
      this.isMoving
    ) {
      this.x = this.targetX
      this.y = this.targetY
      this.isMoving = false
      EventManager.Instance.emit(EVENT_ENUM.PLAYER_MOVE_END)
    }
  }

  inputHandle(inputDirection: CONTROLLER_ENUM) {
    // 移动中不接受输入（不能移动）
    if (this.isMoving) return
    // 死亡状态或者攻击状态不接受输入（不能移动）
    if (
      this.state === ENTITY_STATE_ENUM.DEATH ||
      this.state === ENTITY_STATE_ENUM.AIR_DEATH ||
      this.state === ENTITY_STATE_ENUM.ATTACK
    )
      return

    // 玩家主动攻击
    const enemyId = this.willAttack(inputDirection)

    if (enemyId) {
      EventManager.Instance.emit(EVENT_ENUM.RECORD_STEP)
      this.state = ENTITY_STATE_ENUM.ATTACK
      EventManager.Instance.emit(EVENT_ENUM.ATTACK_ENEMY, enemyId)
      EventManager.Instance.emit(EVENT_ENUM.OPEN_DOOR)
      EventManager.Instance.emit(EVENT_ENUM.PLAYER_MOVE_END)
      return
    }

    // 玩家被阻挡
    if (this.willBlock(inputDirection)) {
      if (inputDirection === CONTROLLER_ENUM.UP) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.UP)
      } else if (inputDirection === CONTROLLER_ENUM.DOWN) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.DOWN)
      } else if (inputDirection === CONTROLLER_ENUM.LEFT) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.LEFT)
      } else if (inputDirection === CONTROLLER_ENUM.RIGHT) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.RIGHT)
      } else if (inputDirection === CONTROLLER_ENUM.TURN_LEFT && this.direction === DIRECTION_ENUM.UP) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.LEFT)
      } else if (inputDirection === CONTROLLER_ENUM.TURN_LEFT && this.direction === DIRECTION_ENUM.LEFT) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.DOWN)
      } else if (inputDirection === CONTROLLER_ENUM.TURN_LEFT && this.direction === DIRECTION_ENUM.DOWN) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.RIGHT)
      } else if (inputDirection === CONTROLLER_ENUM.TURN_LEFT && this.direction === DIRECTION_ENUM.RIGHT) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.UP)
      } else if (inputDirection === CONTROLLER_ENUM.TURN_RIGHT && this.direction === DIRECTION_ENUM.UP) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.RIGHT)
      } else if (inputDirection === CONTROLLER_ENUM.TURN_RIGHT && this.direction === DIRECTION_ENUM.LEFT) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.UP)
      } else if (inputDirection === CONTROLLER_ENUM.TURN_RIGHT && this.direction === DIRECTION_ENUM.DOWN) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.LEFT)
      } else if (inputDirection === CONTROLLER_ENUM.TURN_RIGHT && this.direction === DIRECTION_ENUM.RIGHT) {
        EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, SHAKE_TYPE_ENUM.DOWN)
      }
      return
    }

    this.move(inputDirection)
  }



  onDead(state: ENTITY_STATE_ENUM) {
    if (state === ENTITY_STATE_ENUM.DEATH || state === ENTITY_STATE_ENUM.AIR_DEATH) {
      this.state = state
    }
  }

  willAttack(inputDirection: CONTROLLER_ENUM): string {
    // 过滤死亡的敌人
    const enemies = DataManager.Instance.enemies.filter(enemy => enemy.state !== ENTITY_STATE_ENUM.DEATH)
    for (let i = 0; i < enemies.length; i++) {
      const { x: enemyX, y: enemyY, id: enemyId } = enemies[i]
      if (
        inputDirection === CONTROLLER_ENUM.UP &&
        this.direction === DIRECTION_ENUM.UP &&
        enemyX === this.targetX &&
        enemyY === this.targetY - 2
      ) {
        return enemyId
      }

      if (
        inputDirection === CONTROLLER_ENUM.DOWN &&
        this.direction === DIRECTION_ENUM.DOWN &&
        enemyX === this.targetX &&
        enemyY === this.targetY + 2
      ) {
        return enemyId
      }

      if (
        inputDirection === CONTROLLER_ENUM.LEFT &&
        this.direction === DIRECTION_ENUM.LEFT &&
        enemyX === this.targetX - 2 &&
        enemyY === this.targetY
      ) {
        return enemyId
      }

      if (
        inputDirection === CONTROLLER_ENUM.RIGHT &&
        this.direction === DIRECTION_ENUM.RIGHT &&
        enemyX === this.targetX + 2 &&
        enemyY === this.targetY
      ) {
        return enemyId
      }
    }
    return ''
  }

  onAttackShake(type: SHAKE_TYPE_ENUM) {
    EventManager.Instance.emit(EVENT_ENUM.SCREEN_SHAKE, type)
  }

  willBlock(inputDirection: CONTROLLER_ENUM): boolean {
    const { targetX, targetY, direction } = this
    const { tileInfo } = DataManager.Instance
    const { x: doorX, y: doorY, state: doorState } = DataManager.Instance.door
    const enemies = DataManager.Instance.enemies.filter(enemy => enemy.state !== ENTITY_STATE_ENUM.DEATH)
    const bursts = DataManager.Instance.bursts.filter(burst => burst.state !== ENTITY_STATE_ENUM.DEATH)
    if (inputDirection === CONTROLLER_ENUM.UP) {
      return this.handleInputUpBlock(targetX, targetY, direction, tileInfo, doorX, doorY, doorState, enemies, bursts)
    } else if (inputDirection === CONTROLLER_ENUM.DOWN) {
      return this.handleInputDownBlock(targetX, targetY, direction, tileInfo, doorX, doorY, doorState, enemies, bursts)
    } else if (inputDirection === CONTROLLER_ENUM.LEFT) {
      return this.handleInputLeftBlock(targetX, targetY, direction, tileInfo, doorX, doorY, doorState, enemies, bursts)
    } else if (inputDirection === CONTROLLER_ENUM.RIGHT) {
      return this.handleInputRightBlock(targetX, targetY, direction, tileInfo, doorX, doorY, doorState, enemies, bursts)
    } else if (inputDirection === CONTROLLER_ENUM.TURN_LEFT) {
      return this.handleInputTurnLeftBlock(
        targetX,
        targetY,
        direction,
        tileInfo,
        doorX,
        doorY,
        doorState,
        enemies,
        bursts,
      )
    } else if (inputDirection === CONTROLLER_ENUM.TURN_RIGHT) {
      return this.handleInputTurnRightBlock(
        targetX,
        targetY,
        direction,
        tileInfo,
        doorX,
        doorY,
        doorState,
        enemies,
        bursts,
      )
    }

    return false
  }

  handleInputUpBlock(
    x: number,
    y: number,
    direction: DIRECTION_ENUM,
    tileInfo: TileManager[][],
    doorX: number,
    doorY: number,
    doorState: ENTITY_STATE_ENUM,
    enemies: EnemyManager[],
    bursts: BurstManager[],
  ) {
    let playerNextY: number
    let weaponNextY: number
    let playerTile: TileManager
    let weaponTile: TileManager

    if (direction === DIRECTION_ENUM.UP) {
      // 玩家当前朝向是向上
      playerNextY = y - 1
      weaponNextY = y - 2
      playerTile = tileInfo[x][playerNextY]
      weaponTile = tileInfo[x][weaponNextY]
      // 判断玩家是否超出地图
      if (playerNextY < 0) {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }
      // 判断门
      if (
        ((doorX === x && doorY === playerNextY) || (doorX === x && doorY === weaponNextY)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === x && enemyY === playerNextY) || (enemyX === x && enemyY === weaponNextY)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
          return true
        }
      }

      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === x && burstY === playerNextY && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }

      // 判断地图Tile元素
      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }
    } else if (direction === DIRECTION_ENUM.DOWN) {
      // 玩家当前朝向是向下
      playerNextY = y - 1
      weaponNextY = y
      playerTile = tileInfo[x][playerNextY]
      weaponTile = tileInfo[x][weaponNextY]
      if (playerNextY < 0) {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
      // 判断门
      if (
        ((doorX === x && doorY === playerNextY) || (doorX === x && doorY === weaponNextY)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === x && enemyY === playerNextY) || (enemyX === x && enemyY === weaponNextY)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_BACK
          return true
        }
      }
      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === x && burstY === playerNextY && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }
      // 判断地图Tile元素
      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
    } else if (direction === DIRECTION_ENUM.LEFT) {
      // 玩家当前朝向是向左
      playerNextY = y - 1
      weaponNextY = y - 1
      playerTile = tileInfo[x][playerNextY]
      weaponTile = tileInfo[x - 1][weaponNextY]
      if (playerNextY < 0) {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
      // 判断门
      if (
        ((doorX === x && doorY === playerNextY) || (doorX === x && doorY === weaponNextY)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === x && enemyY === playerNextY) || (enemyX === x && enemyY === weaponNextY)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
          return true
        }
      }
      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === x && burstY === playerNextY && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }
      // 判断地图Tile元素
      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
    } else if (direction === DIRECTION_ENUM.RIGHT) {
      // 玩家当前朝向是向右
      playerNextY = y - 1
      weaponNextY = y - 1
      playerTile = tileInfo[x][playerNextY]
      weaponTile = tileInfo[x + 1][weaponNextY]
      if (playerNextY < 0) {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }
      // 判断门
      if (
        ((doorX === x && doorY === playerNextY) || (doorX === x && doorY === weaponNextY)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === x && enemyY === playerNextY) || (enemyX === x && enemyY === weaponNextY)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
          return true
        }
      }
      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === x && burstY === playerNextY && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }
      // 判断地图Tile元素
      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }
    }
  }

  handleInputDownBlock(
    x: number,
    y: number,
    direction: DIRECTION_ENUM,
    tileInfo: TileManager[][],
    doorX: number,
    doorY: number,
    doorState: ENTITY_STATE_ENUM,
    enemies: EnemyManager[],
    bursts: BurstManager[],
  ) {
    let playerNextY: number
    let weaponNextY: number
    let playerTile: TileManager
    let weaponTile: TileManager
    const { mapRowCount } = DataManager.Instance

    if (direction === DIRECTION_ENUM.UP) {
      playerNextY = y + 1
      weaponNextY = y
      playerTile = tileInfo[x][playerNextY]
      weaponTile = tileInfo[x][weaponNextY]
      if (playerNextY > mapRowCount) {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
      // 判断门
      if (
        ((doorX === x && doorY === playerNextY) || (doorX === x && doorY === weaponNextY)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === x && enemyY === playerNextY) || (enemyX === x && enemyY === weaponNextY)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_BACK
          return true
        }
      }

      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === x && burstY === playerNextY && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }

      // 判断地图Tile元素
      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
    } else if (direction === DIRECTION_ENUM.DOWN) {
      playerNextY = y + 1
      weaponNextY = y + 2
      playerTile = tileInfo[x][playerNextY]
      weaponTile = tileInfo[x][weaponNextY]
      if (playerNextY > mapRowCount) {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }
      // 判断门
      if (
        ((doorX === x && doorY === playerNextY) || (doorX === x && doorY === weaponNextY)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === x && enemyY === playerNextY) || (enemyX === x && enemyY === weaponNextY)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
          return true
        }
      }
      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === x && burstY === playerNextY && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }
      // 判断地图Tile元素
      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }
    } else if (direction === DIRECTION_ENUM.LEFT) {
      playerNextY = y + 1
      weaponNextY = y + 1
      playerTile = tileInfo[x][playerNextY]
      weaponTile = tileInfo[x - 1][weaponNextY]
      if (playerNextY > mapRowCount) {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
      // 判断门
      if (
        ((doorX === x && doorY === playerNextY) || (doorX === x && doorY === weaponNextY)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === x && enemyY === playerNextY) || (enemyX === x && enemyY === weaponNextY)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
          return true
        }
      }
      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === x && burstY === playerNextY && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }
      // 判断地图Tile元素
      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
    } else if (direction === DIRECTION_ENUM.RIGHT) {
      playerNextY = y + 1
      weaponNextY = y + 1
      playerTile = tileInfo[x][playerNextY]
      weaponTile = tileInfo[x + 1][weaponNextY]
      if (playerNextY > mapRowCount) {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }
      // 判断门
      if (
        ((doorX === x && doorY === playerNextY) || (doorX === x && doorY === weaponNextY)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === x && enemyY === playerNextY) || (enemyX === x && enemyY === weaponNextY)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
          return true
        }
      }
      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === x && burstY === playerNextY && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }
      // 判断地图Tile元素
      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }
    }
  }

  handleInputLeftBlock(
    x: number,
    y: number,
    direction: DIRECTION_ENUM,
    tileInfo: TileManager[][],
    doorX: number,
    doorY: number,
    doorState: ENTITY_STATE_ENUM,
    enemies: EnemyManager[],
    bursts: BurstManager[],
  ) {
    let playerNextX: number
    let weaponNextX: number
    let playerTile: TileManager
    let weaponTile: TileManager

    if (direction === DIRECTION_ENUM.UP) {
      playerNextX = x - 1
      weaponNextX = x - 1
      playerTile = tileInfo[playerNextX][y]
      weaponTile = tileInfo[weaponNextX][y]

      if (playerNextX < 0) {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }

      // 判断门
      if (
        ((doorY === y && doorX === playerNextX) || (doorY === y && doorX === weaponNextX)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === playerNextX && enemyY === y) || (enemyX === weaponNextX && enemyY === y)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
          return true
        }
      }

      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === playerNextX && burstY === y && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }

      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }
    } else if (direction === DIRECTION_ENUM.DOWN) {
      playerNextX = x - 1
      weaponNextX = x - 1
      playerTile = tileInfo[playerNextX][y]
      weaponTile = tileInfo[weaponNextX][y]
      if (playerNextX < 0) {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }

      // 判断门
      if (
        ((doorY === y && doorX === playerNextX) || (doorY === y && doorX === weaponNextX)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === playerNextX && enemyY === y) || (enemyX === weaponNextX && enemyY === y)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
          return true
        }
      }

      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === playerNextX && burstY === y && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }

      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
    } else if (direction === DIRECTION_ENUM.LEFT) {
      playerNextX = x - 1
      weaponNextX = x - 2
      playerTile = tileInfo[playerNextX][y]
      weaponTile = tileInfo[weaponNextX][y]
      if (playerNextX < 0) {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }
      // 判断门
      if (
        ((doorY === y && doorX === playerNextX) || (doorY === y && doorX === weaponNextX)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === playerNextX && enemyY === y) || (enemyX === weaponNextX && enemyY === y)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
          return true
        }
      }
      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === playerNextX && burstY === y && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }

      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }
    } else if (direction === DIRECTION_ENUM.RIGHT) {
      playerNextX = x - 1
      weaponNextX = x
      playerTile = tileInfo[playerNextX][y]
      weaponTile = tileInfo[weaponNextX][y]
      if (playerNextX < 0) {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
      // 判断门
      if (
        ((doorY === y && doorX === playerNextX) || (doorY === y && doorX === weaponNextX)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === playerNextX && enemyY === y) || (enemyX === weaponNextX && enemyY === y)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_BACK
          return true
        }
      }

      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === playerNextX && burstY === y && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }

      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
    }
  }

  handleInputRightBlock(
    x: number,
    y: number,
    direction: DIRECTION_ENUM,
    tileInfo: TileManager[][],
    doorX: number,
    doorY: number,
    doorState: ENTITY_STATE_ENUM,
    enemies: EnemyManager[],
    bursts: BurstManager[],
  ) {
    let playerNextX: number
    let weaponNextX: number
    let playerTile: TileManager
    let weaponTile: TileManager
    const { mapColCount } = DataManager.Instance

    if (direction === DIRECTION_ENUM.UP) {
      playerNextX = x + 1
      weaponNextX = x + 1
      playerTile = tileInfo[playerNextX][y]
      weaponTile = tileInfo[weaponNextX][y]

      if (playerNextX > mapColCount) {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }

      // 判断门
      if (
        ((doorY === y && doorX === playerNextX) || (doorY === y && doorX === weaponNextX)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === playerNextX && enemyY === y) || (enemyX === weaponNextX && enemyY === y)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
          return true
        }
      }

      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === playerNextX && burstY === y && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }

      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
    } else if (direction === DIRECTION_ENUM.DOWN) {
      playerNextX = x + 1
      weaponNextX = x + 1
      playerTile = tileInfo[playerNextX][y]
      weaponTile = tileInfo[weaponNextX][y]
      if (playerNextX > mapColCount) {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }

      // 判断门
      if (
        ((doorY === y && doorX === playerNextX) || (doorY === y && doorX === weaponNextX)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === playerNextX && enemyY === y) || (enemyX === weaponNextX && enemyY === y)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
          return true
        }
      }

      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === playerNextX && burstY === y && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }

      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_LEFT
        return true
      }
    } else if (direction === DIRECTION_ENUM.LEFT) {
      playerNextX = x + 1
      weaponNextX = x
      playerTile = tileInfo[playerNextX][y]
      weaponTile = tileInfo[weaponNextX][y]
      if (playerNextX > mapColCount) {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }

      // 判断门
      if (
        ((doorY === y && doorX === playerNextX) || (doorY === y && doorX === weaponNextX)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === playerNextX && enemyY === y) || (enemyX === weaponNextX && enemyY === y)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_BACK
          return true
        }
      }
      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === playerNextX && burstY === y && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }

      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_BACK
        return true
      }
    } else if (direction === DIRECTION_ENUM.RIGHT) {
      playerNextX = x + 1
      weaponNextX = x + 2

      playerTile = tileInfo[playerNextX][y]
      weaponTile = tileInfo[weaponNextX][y]
      if (playerNextX > mapColCount) {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }

      // 判断门
      if (
        ((doorY === y && doorX === playerNextX) || (doorY === y && doorX === weaponNextX)) &&
        doorState !== ENTITY_STATE_ENUM.DEATH
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_RIGHT
        return true
      }
      // 判断敌人
      for (let i = 0; i < enemies.length; i++) {
        const { x: enemyX, y: enemyY } = enemies[i]
        if ((enemyX === playerNextX && enemyY === y) || (enemyX === weaponNextX && enemyY === y)) {
          this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
          return true
        }
      }
      // 判断地刺
      for (let i = 0; i < bursts.length; i++) {
        const { x: burstX, y: burstY } = bursts[i]
        if (burstX === playerNextX && burstY === y && (!weaponTile || weaponTile.turnable)) {
          return false
        }
      }

      if (playerTile && playerTile.moveable && (!weaponTile || weaponTile.turnable)) {
        // emety
      } else {
        this.state = ENTITY_STATE_ENUM.BLOCK_FRONT
        return true
      }
    }
  }

  handleInputTurnLeftBlock(
    x: number,
    y: number,
    direction: DIRECTION_ENUM,
    tileInfo: TileManager[][],
    doorX: number,
    doorY: number,
    doorState: ENTITY_STATE_ENUM,
    enemies: EnemyManager[],
    bursts: BurstManager[],
  ) {
    let nextX: number
    let nextY: number
    if (direction === DIRECTION_ENUM.UP) {
      nextX = x - 1
      nextY = y - 1
    } else if (direction === DIRECTION_ENUM.DOWN) {
      nextX = x + 1
      nextY = y + 1
    } else if (direction === DIRECTION_ENUM.LEFT) {
      nextX = x - 1
      nextY = y + 1
    } else if (direction === DIRECTION_ENUM.RIGHT) {
      nextX = x + 1
      nextY = y - 1
    }

    // 判断门
    if (
      ((x === doorX && nextY === doorY) || (nextX === doorX && y === doorY) || (nextX === doorX && nextY === doorY)) &&
      doorState !== ENTITY_STATE_ENUM.DEATH
    ) {
      this.state = ENTITY_STATE_ENUM.BLOCK_TURN_LEFT
      return true
    }
    // 判断敌人
    for (let i = 0; i < enemies.length; i++) {
      const { x: enemyX, y: enemyY } = enemies[i]
      if (
        (x === enemyX && nextY === enemyY) ||
        (nextX === enemyX && y === enemyY) ||
        (nextX === enemyX && nextY === enemyY)
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_TURN_LEFT
        return true
      }
    }
    // 能左转需要判断武器经过的格子的配置是否为允许旋转或者不存在格子（悬崖）
    if (
      (!tileInfo[x][nextY] || tileInfo[x][nextY].turnable) &&
      (!tileInfo[nextX][y] || tileInfo[nextX][y].turnable) &&
      (!tileInfo[nextX][nextY] || tileInfo[nextX][nextY].turnable)
    ) {
      // empty
    } else {
      this.state = ENTITY_STATE_ENUM.BLOCK_TURN_LEFT
      return true
    }
  }

  handleInputTurnRightBlock(
    x: number,
    y: number,
    direction: DIRECTION_ENUM,
    tileInfo: TileManager[][],
    doorX: number,
    doorY: number,
    doorState: ENTITY_STATE_ENUM,
    enemies: EnemyManager[],
    bursts: BurstManager[],
  ) {
    let nextX: number
    let nextY: number
    if (direction === DIRECTION_ENUM.UP) {
      nextX = x + 1
      nextY = y - 1
    } else if (direction === DIRECTION_ENUM.DOWN) {
      nextX = x - 1
      nextY = y + 1
    } else if (direction === DIRECTION_ENUM.LEFT) {
      nextX = x - 1
      nextY = y - 1
    } else if (direction === DIRECTION_ENUM.RIGHT) {
      nextX = x + 1
      nextY = y + 1
    }

    // 判断门
    if (
      ((x === doorX && nextY === doorY) || (nextX === doorX && y === doorY) || (nextX === doorX && nextY === doorY)) &&
      doorState !== ENTITY_STATE_ENUM.DEATH
    ) {
      this.state = ENTITY_STATE_ENUM.BLOCK_TURN_RIGHT
      return true
    }
    // 判断敌人
    for (let i = 0; i < enemies.length; i++) {
      const { x: enemyX, y: enemyY } = enemies[i]
      if (
        (x === enemyX && nextY === enemyY) ||
        (nextX === enemyX && y === enemyY) ||
        (nextX === enemyX && nextY === enemyY)
      ) {
        this.state = ENTITY_STATE_ENUM.BLOCK_TURN_RIGHT
        return true
      }
    }

    // 能右转需要判断武器经过的格子的配置是否为允许旋转或者不存在格子（悬崖）
    if (
      (!tileInfo[x][nextY] || tileInfo[x][nextY].turnable) &&
      (!tileInfo[nextX][y] || tileInfo[nextX][y].turnable) &&
      (!tileInfo[nextX][nextY] || tileInfo[nextX][nextY].turnable)
    ) {
      // empty
    } else {
      this.state = ENTITY_STATE_ENUM.BLOCK_TURN_RIGHT
      return true
    }
  }

  move(inputDirection: CONTROLLER_ENUM) {
    // 记录数据
    EventManager.Instance.emit(EVENT_ENUM.RECORD_STEP)
    switch (inputDirection) {
      case CONTROLLER_ENUM.UP:
        this.targetY -= 1
        this.isMoving = true
        this.showSmoke(inputDirection as unknown as DIRECTION_ENUM)
        break
      case CONTROLLER_ENUM.DOWN:
        this.targetY += 1
        this.isMoving = true
        this.showSmoke(inputDirection as unknown as DIRECTION_ENUM)
        break
      case CONTROLLER_ENUM.LEFT:
        this.targetX -= 1
        this.isMoving = true
        this.showSmoke(inputDirection as unknown as DIRECTION_ENUM)
        break
      case CONTROLLER_ENUM.RIGHT:
        this.targetX += 1
        this.isMoving = true
        this.showSmoke(inputDirection as unknown as DIRECTION_ENUM)
        break

      case CONTROLLER_ENUM.TURN_LEFT:
        this.handleMoveTurnLeft()
        break
      case CONTROLLER_ENUM.TURN_RIGHT:
        this.handleMoveTurnRight()
        break
    }
  }

  showSmoke(inputDirection: DIRECTION_ENUM) {
    EventManager.Instance.emit(EVENT_ENUM.SHOW_SMOKE,this.x,this.y,inputDirection)
  }

  handleMoveTurnLeft() {
    if (this.direction === DIRECTION_ENUM.UP) {
      this.direction = DIRECTION_ENUM.LEFT
    } else if (this.direction === DIRECTION_ENUM.LEFT) {
      this.direction = DIRECTION_ENUM.DOWN
    } else if (this.direction === DIRECTION_ENUM.DOWN) {
      this.direction = DIRECTION_ENUM.RIGHT
    } else if (this.direction === DIRECTION_ENUM.RIGHT) {
      this.direction = DIRECTION_ENUM.UP
    }

    this.state = ENTITY_STATE_ENUM.TURN_LEFT
    EventManager.Instance.emit(EVENT_ENUM.PLAYER_MOVE_END)
  }

  handleMoveTurnRight() {
    if (this.direction === DIRECTION_ENUM.UP) {
      this.direction = DIRECTION_ENUM.RIGHT
    } else if (this.direction === DIRECTION_ENUM.RIGHT) {
      this.direction = DIRECTION_ENUM.DOWN
    } else if (this.direction === DIRECTION_ENUM.DOWN) {
      this.direction = DIRECTION_ENUM.LEFT
    } else if (this.direction === DIRECTION_ENUM.LEFT) {
      this.direction = DIRECTION_ENUM.UP
    }
    this.state = ENTITY_STATE_ENUM.TURN_RIGHT
    EventManager.Instance.emit(EVENT_ENUM.PLAYER_MOVE_END)
  }
}
